{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 163,
   "metadata": {},
   "outputs": [],
   "source": [
    "#model based CF\n",
    "from __future__ import division  \n",
    "import numpy as np  \n",
    "import scipy as sp  \n",
    "from numpy.random import random  \n",
    "from decimal import Decimal \n",
    "class  SVD_CF:  \n",
    "    def __init__(self, X, k=20):  \n",
    "        ''''' \n",
    "            k  is the number of latent componets \n",
    "        '''  \n",
    "        self.X = X  \n",
    "        self.k = k  \n",
    "        self.mu = np.mean(self.X[:,2])  #average rating\n",
    "        \n",
    "        #init parameters\n",
    "        self.bi={}  \n",
    "        self.bu={}  \n",
    "        \n",
    "        self.qi={}  \n",
    "        self.pu={}  \n",
    "        \n",
    "        self.ItemsForUser={}  #每个Item对应的用户\n",
    "        self.UsersForItem={}  #每个用户对哪些Item打过分\n",
    "        self.song=set()\n",
    "        for i in range(self.X.shape[0]):  \n",
    "            uid=self.X[i][0]  #user id\n",
    "            i_id=self.X[i][1] #item_id \n",
    "            rat=self.X[i][2]  #rating\n",
    "            self.song.add(i_id)\n",
    "            self.ItemsForUser.setdefault(i_id,{})  \n",
    "            self.UsersForItem.setdefault(uid,{}) \n",
    "            \n",
    "            self.ItemsForUser[i_id][uid]=rat  \n",
    "            self.UsersForItem[uid][i_id]=rat  \n",
    "            \n",
    "            self.bi.setdefault(i_id,0)  \n",
    "            self.bu.setdefault(uid,0)  \n",
    "            \n",
    "            self.qi.setdefault(i_id,random((self.k,1))/10*(np.sqrt(self.k)))  \n",
    "          \n",
    "            self.pu.setdefault(uid,random((self.k,1))/10*(np.sqrt(self.k)))  \n",
    "                    \n",
    "    #根据当前参数，预测用户uid对Item（i_id）的打分\n",
    "    def pred(self,uid,i_id):  \n",
    "        self.bi.setdefault(i_id,0)  \n",
    "        self.bu.setdefault(uid,0)  \n",
    "        \n",
    "        self.qi.setdefault(i_id,np.zeros((self.k,1)))  \n",
    "        self.pu.setdefault(uid,np.zeros((self.k,1)))  \n",
    "        \n",
    "        if (self.qi[i_id].all()==None):  \n",
    "            self.qi[i_id]=np.zeros((self.k,1))  \n",
    "        if (self.pu[uid].all()==None):  \n",
    "            self.pu[uid]=np.zeros((self.k,1))  \n",
    "        \n",
    "        ans=self.mu + self.bi[i_id] + self.bu[uid] + np.sum(self.qi[i_id]*self.pu[uid])  \n",
    "        \n",
    "        #将打分范围控制在1-5之间\n",
    "        if ans>5:  \n",
    "            return 5  \n",
    "        elif ans<1:  \n",
    "            return 1  \n",
    "        return ans  \n",
    "    \n",
    "    #gamma：为学习率\n",
    "    #Lambda：正则参数\n",
    "    def train(self,steps=50,gamma=0.04,Lambda=0.15):  \n",
    "        for step in range(steps):  \n",
    "            print( 'the %d -th  step is running' %step ) \n",
    "            rmse_sum=0.0 \n",
    "            z=0\n",
    "            #将训练样本打散顺序\n",
    "            kk = np.random.permutation(self.X.shape[0])  \n",
    "            for j in range(self.X.shape[0]):  \n",
    "                \n",
    "                #每次一个训练样本\n",
    "                i=kk[j]  \n",
    "                uid=self.X[i][0]  \n",
    "                i_id=self.X[i][1]  \n",
    "                rat=self.X[i][2]  \n",
    "                \n",
    "                #预测残差\n",
    "                eui=rat-self.pred(uid,i_id)  \n",
    "                eui=round(eui,4)  \n",
    "                \n",
    "            #残差平方\n",
    "                rmse_sum+=eui**2  \n",
    "            \n",
    "                #随机梯度下降，更新\n",
    "                self.bu[uid]+=gamma*(eui-Lambda*self.bu[uid])  \n",
    "                self.bi[i_id]+=gamma*(eui-Lambda*self.bi[i_id]) \n",
    "        \n",
    "                temp=self.qi[i_id]\n",
    "           \n",
    "                for i in range(len(self.qi[i_id])):\n",
    "                    self.qi[i_id][i][0]=self.qi[i_id][i][0]\n",
    "                for i in range(len(self.pu[uid])):\n",
    "                    self.pu[uid][i][0]=self.pu[uid][i][0]\n",
    "              \n",
    "                if step==1 and z==0:\n",
    "                    z=z+1\n",
    "                    print(rat)\n",
    "                    print(eui)\n",
    "                    print(self.pu[uid])\n",
    "                    print(Lambda)\n",
    "                    print(self.qi[i_id])\n",
    "            \n",
    "                if (step==7 or step==8) and z==0:\n",
    "                    z=z+1\n",
    "                    print(rat)\n",
    "                    print(eui)\n",
    "                    print(self.pu[uid])\n",
    "                    print(Lambda)\n",
    "                    print(self.qi[i_id])\n",
    "                \n",
    "                self.qi[i_id]+=gamma*(eui*self.pu[uid]-Lambda*self.qi[i_id])  \n",
    "                self.pu[uid]+=gamma*(eui*temp-Lambda*self.pu[uid])\n",
    "         \n",
    "            #学习率递减\n",
    "            gamma=round(gamma*0.93,4)  \n",
    "            print(\"the rmse of this step on train data is %f \"%np.sqrt(rmse_sum/self.X.shape[0]))  \n",
    "            #self.test(test_data)  \n",
    "            \n",
    "    def test(self,uid):  \n",
    "        output=[] \n",
    "        score={}\n",
    "        i=0 \n",
    "        index=-1\n",
    "        minvalue=-1\n",
    "        for i_id in self.song:  #对每个测试样本\n",
    "            pre=self.pred(uid,i_id)  #预测打分\n",
    "            if i<20:#推荐20个歌曲\n",
    "                    score[i_id]=pre\n",
    "                    i=i+1\n",
    "            else:\n",
    "                    for j in score:\n",
    "                            minvalue=-1  \n",
    "                            index=-1\n",
    "                            if minvalue>score[j]:\n",
    "                                minvalue=score[j]\n",
    "                                index=j\n",
    "                    if index!=-1:\n",
    "                        del score[index]\n",
    "                        score[i_id]=pre\n",
    "                    \n",
    "                    \n",
    "                    \n",
    "       \n",
    "        return score.keys()\n",
    "    \n",
    "    \n",
    "    \n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn import preprocessing\n",
    "from sklearn.model_selection import train_test_split"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 165,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user</th>\n",
       "      <th>song</th>\n",
       "      <th>listen_count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>13ce57b3a25ef63fa614335fd838e8024c42ec17</td>\n",
       "      <td>SOAAGFH12A8C13D072</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>13ce57b3a25ef63fa614335fd838e8024c42ec17</td>\n",
       "      <td>SOABMLY12AF72A86B1</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>13ce57b3a25ef63fa614335fd838e8024c42ec17</td>\n",
       "      <td>SOADQYG12AB0189D58</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>13ce57b3a25ef63fa614335fd838e8024c42ec17</td>\n",
       "      <td>SOAFSJL12AB017D792</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>13ce57b3a25ef63fa614335fd838e8024c42ec17</td>\n",
       "      <td>SOAIAGB12AB017D7D4</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                       user                song  listen_count\n",
       "0  13ce57b3a25ef63fa614335fd838e8024c42ec17  SOAAGFH12A8C13D072             1\n",
       "1  13ce57b3a25ef63fa614335fd838e8024c42ec17  SOABMLY12AF72A86B1             1\n",
       "2  13ce57b3a25ef63fa614335fd838e8024c42ec17  SOADQYG12AB0189D58             1\n",
       "3  13ce57b3a25ef63fa614335fd838e8024c42ec17  SOAFSJL12AB017D792             4\n",
       "4  13ce57b3a25ef63fa614335fd838e8024c42ec17  SOAIAGB12AB017D7D4             6"
      ]
     },
     "execution_count": 165,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = pd.read_csv('triplet_dataset_sub_song_merged.csv')\n",
    "user_count_df = pd.read_csv('user_playcount_df.csv')\n",
    "user_count_subset = user_count_df.head(n=200)\n",
    "user_subset = list(user_count_subset.user)\n",
    "data_sub1 = data[data.user.isin(user_subset)]\n",
    "\n",
    "data_sub1=data_sub1.drop('title',axis=1)\n",
    "data_sub1=data_sub1.drop('release',axis=1)\n",
    "data_sub1=data_sub1.drop('artist_name',axis=1)\n",
    "data_sub1=data_sub1.drop('year',axis=1)\n",
    "#a=data_sub1['listen_count'].max()\n",
    "#i=data_sub1['listen_count'].min()\n",
    "#data_sub1['listen_count']-i/a-i\n",
    "\n",
    "data_sub1=data_sub1.reset_index(drop=True)\n",
    "data_sub1.head()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 166,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "h\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\anaconda3\\lib\\site-packages\\sklearn\\utils\\validation.py:475: DataConversionWarning: Data with input dtype int64 was converted to float64 by MinMaxScaler.\n",
      "  warnings.warn(msg, DataConversionWarning)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>news</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.000310</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.000517</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       news\n",
       "0  0.000000\n",
       "1  0.000000\n",
       "2  0.000000\n",
       "3  0.000310\n",
       "4  0.000517"
      ]
     },
     "execution_count": 166,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "c=data_sub1['listen_count'].count()\n",
    "\n",
    "X=np.array(data_sub1['listen_count']).reshape(c,1)\n",
    "\n",
    "#data_sub=np.array([[1,2,3] [1,2,3]])\n",
    "\n",
    "#data_sub = np.array([[1, -1, 2]])\n",
    "min_max_scaler = preprocessing.MinMaxScaler()\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "X=min_max_scaler.fit_transform(X)\n",
    "X=X.flatten()\n",
    "print('h')\n",
    "df1=pd.DataFrame({'news':X})\n",
    "df1.head()\n",
    "#pd.concat([data_sub,df1],ignore_index=True,axis=1)\n",
    "#data_sub=pd.DataFrame()\n",
    "#data_sub.head()\n",
    "\n",
    "\n",
    "\n",
    "#data_sub.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 66207 entries, 0 to 66206\n",
      "Data columns (total 4 columns):\n",
      "user            66207 non-null object\n",
      "song            66207 non-null object\n",
      "listen_count    66207 non-null int64\n",
      "news            66207 non-null float64\n",
      "dtypes: float64(1), int64(1), object(2)\n",
      "memory usage: 2.0+ MB\n"
     ]
    }
   ],
   "source": [
    "data_sub1=pd.DataFrame(data_sub1)\n",
    "\n",
    "data_sub1=pd.concat([data_sub1,df1],axis=1)\n",
    "data_sub1.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 168,
   "metadata": {},
   "outputs": [],
   "source": [
    "data_sub1=data_sub1.drop('listen_count',axis=1)\n",
    "data_sub, test = train_test_split(data_sub1, test_size = 0.40, random_state=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 169,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "the 0 -th  step is running\n",
      "the rmse of this step on train data is 1.000104 \n",
      "the 1 -th  step is running\n",
      "0.0\n",
      "-1.0\n",
      "[[-1.92248545]\n",
      " [-1.92405938]\n",
      " [-1.92646992]\n",
      " [-1.91086795]\n",
      " [-1.91247333]\n",
      " [-2.00426474]\n",
      " [-1.94623895]\n",
      " [-1.97792834]\n",
      " [-2.10094929]\n",
      " [-1.99845315]\n",
      " [-2.08049914]\n",
      " [-1.95767478]\n",
      " [-2.00623187]\n",
      " [-2.12518995]\n",
      " [-1.9837837 ]\n",
      " [-2.13793604]\n",
      " [-1.95685743]\n",
      " [-2.08475269]\n",
      " [-1.84129819]\n",
      " [-2.02221835]]\n",
      "0.15\n",
      "[[0.6651755 ]\n",
      " [0.48823303]\n",
      " [0.38063124]\n",
      " [0.61987912]\n",
      " [0.69565322]\n",
      " [0.51447343]\n",
      " [0.41141111]\n",
      " [0.44127023]\n",
      " [0.43325154]\n",
      " [0.66936132]\n",
      " [0.48740088]\n",
      " [0.47645854]\n",
      " [0.36737102]\n",
      " [0.44772193]\n",
      " [0.4338258 ]\n",
      " [0.59994543]\n",
      " [0.53600393]\n",
      " [0.60298521]\n",
      " [0.73169954]\n",
      " [0.49227412]]\n",
      "the rmse of this step on train data is 0.999491 \n",
      "the 2 -th  step is running\n",
      "the rmse of this step on train data is 0.999296 \n",
      "the 3 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 4 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 5 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 6 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 7 -th  step is running\n",
      "0.0\n",
      "-1.0\n",
      "[[-62.04091785]\n",
      " [-61.49097361]\n",
      " [-61.46870166]\n",
      " [-61.29522352]\n",
      " [-60.87232793]\n",
      " [-61.38353121]\n",
      " [-61.47710868]\n",
      " [-61.24556876]\n",
      " [-62.26536487]\n",
      " [-61.94773448]\n",
      " [-60.82785362]\n",
      " [-61.41153355]\n",
      " [-61.73108869]\n",
      " [-61.87223298]\n",
      " [-61.94850452]\n",
      " [-62.15502056]\n",
      " [-61.82919454]\n",
      " [-61.31796864]\n",
      " [-61.49306987]\n",
      " [-61.57693512]]\n",
      "0.15\n",
      "[[9.99236911]\n",
      " [9.58551173]\n",
      " [9.6267291 ]\n",
      " [9.81021674]\n",
      " [9.78733741]\n",
      " [9.57168151]\n",
      " [9.71947254]\n",
      " [9.81701675]\n",
      " [9.76312421]\n",
      " [9.95535236]\n",
      " [9.69523104]\n",
      " [9.63368123]\n",
      " [9.9231179 ]\n",
      " [9.81662541]\n",
      " [9.73641783]\n",
      " [9.75042031]\n",
      " [9.70111009]\n",
      " [9.55876261]\n",
      " [9.66001733]\n",
      " [9.53268422]]\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 8 -th  step is running\n",
      "0.0\n",
      "-1.0\n",
      "[[-530.77432586]\n",
      " [-521.49226358]\n",
      " [-525.00388188]\n",
      " [-523.71038907]\n",
      " [-518.26076208]\n",
      " [-523.72503942]\n",
      " [-524.16375388]\n",
      " [-525.30658494]\n",
      " [-530.69599102]\n",
      " [-527.68637531]\n",
      " [-520.58815312]\n",
      " [-523.32494961]\n",
      " [-527.39800927]\n",
      " [-525.3170739 ]\n",
      " [-526.3881945 ]\n",
      " [-531.06518074]\n",
      " [-529.15874451]\n",
      " [-525.36021904]\n",
      " [-526.22679225]\n",
      " [-526.37846744]]\n",
      "0.15\n",
      "[[81.58440586]\n",
      " [80.21633048]\n",
      " [80.58231974]\n",
      " [80.37107519]\n",
      " [79.62486899]\n",
      " [80.48416538]\n",
      " [80.24312355]\n",
      " [80.72393224]\n",
      " [81.63635299]\n",
      " [80.84579672]\n",
      " [80.03945739]\n",
      " [80.40913335]\n",
      " [81.0246869 ]\n",
      " [80.54061271]\n",
      " [80.77039862]\n",
      " [81.39885675]\n",
      " [81.08279703]\n",
      " [80.63968914]\n",
      " [80.43557199]\n",
      " [80.80029658]]\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 9 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 10 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 11 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 12 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 13 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 14 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 15 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 16 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 17 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 18 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 19 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 20 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 21 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 22 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 23 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 24 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 25 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 26 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 27 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 28 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 29 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 30 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 31 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 32 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 33 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 34 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 35 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 36 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 37 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 38 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 39 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 40 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 41 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 42 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 43 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 44 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 45 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 46 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 47 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 48 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n",
      "the 49 -th  step is running\n",
      "the rmse of this step on train data is 0.999270 \n"
     ]
    }
   ],
   "source": [
    "movie_SVD_CF = SVD_CF(data_sub.values)\n",
    "\n",
    "movie_SVD_CF.train()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 174,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "22\n",
      "26483\n",
      "4000\n",
      "准确率0.005500\n",
      "召回率0.000831\n"
     ]
    }
   ],
   "source": [
    "from collections import defaultdict\n",
    "at=0\n",
    "aj=0\n",
    "tp=0\n",
    "\n",
    "y=set()\n",
    "uniqueUsers2=set(test['user'])\n",
    "songsforUsers2=defaultdict(set)\n",
    "for k in test.index: \n",
    "    songsforUsers2[test.loc[k,'user']].add(test.loc[k,'song'])\n",
    "\n",
    "for u in uniqueUsers2:\n",
    "    q=movie_SVD_CF.test(u)\n",
    "    y=set(q)\n",
    "    ssong=set(songsforUsers2[u])\n",
    "    tp=len(y.intersection(ssong))+tp\n",
    "    at=len(ssong)+at\n",
    "    aj=aj+len(y) \n",
    "        \n",
    "        \n",
    "print(tp)\n",
    "print(at)\n",
    "print(aj)\n",
    "          \n",
    "p=tp/aj\n",
    "r=tp/at\n",
    "print(\"准确率%f\"%p)\n",
    "print(\"召回率%f\"%r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
